package com.cg.service.impl;

import com.cg.dto.ChatSessionDTO;
import com.cg.dto.ChatMessageDTO;
import com.cg.mapper.ChatSessionMapper;
import com.cg.service.ChatMemoryService;
import com.cg.constant.RedisConstant;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.data.message.AiMessage;
import dev.langchain4j.memory.ChatMemory;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * ChatMemory管理服务实现类
 */
@Slf4j
@Service
public class ChatMemoryServiceImpl implements ChatMemoryService {
    
    private static final int REDIS_EXPIRE_TIME = RedisConstant.CHAT_MEMORY_EXPIRE_TIME;
    
    @Autowired
    private ChatSessionMapper chatSessionMapper;
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    @Override
    public ChatSessionDTO createChatSession(Long userId, String initialMessage) {
        try {
            // 创建会话DTO
            ChatSessionDTO session = new ChatSessionDTO();
            session.setUserId(userId);
            
            // 如果没有初始消息，使用默认标题
            if (initialMessage == null || initialMessage.trim().isEmpty()) {
                session.setSessionTitle("新会话");
            } else {
                session.setSessionTitle(initialMessage.length() > 50 ? 
                        initialMessage.substring(0, 50) + "..." : initialMessage);
            }
            
            session.setStatus("active");
            session.setSessionType("chat"); // 默认为普通问答类型
            session.setMessageCount(0);
            session.setLastActiveTime(new Date());
            session.setCreateTime(new Date());
            session.setUpdateTime(new Date());
            
            // 保存会话到数据库
            int result = chatSessionMapper.createSession(session);
            if (result <= 0) {
                throw new RuntimeException("创建会话失败");
            }
            
            // 获取生成的sessionId
            Long sessionId = session.getSessionId();
            if (sessionId == null) {
                throw new RuntimeException("会话ID生成失败");
            }
            
            // 不落库"新会话/新对话"占位，但立即设置标题为占位，等待第一条真实用户消息时更新
            if (initialMessage != null && !initialMessage.trim().isEmpty() &&
                !"新会话".equals(initialMessage.trim()) &&
                !"新对话".equals(initialMessage.trim())) {
                addUserMessage(sessionId, initialMessage.trim());
                // 首条真实消息即标题，可在此就生成简短标题
                String title = initialMessage.trim();
                if (title.length() > 10) {
                    title = title.substring(0, 10) + "...";
                }
                updateSessionTitle(sessionId, title);
            }
            
            // 初始化Redis缓存
            initializeRedisChatMemory(sessionId);
            
            log.info("聊天会话创建成功: sessionId={}, userId={}, title={}", 
                    sessionId, userId, session.getSessionTitle());
            
            return session;
            
        } catch (Exception e) {
            log.error("创建聊天会话失败: userId={}, error={}", userId, e.getMessage(), e);
            throw new RuntimeException("创建聊天会话失败", e);
        }
    }

    @Override
    public ChatSessionDTO createChatSession(Long userId, String sessionTitle, String sessionType) {
        try {
            // 创建会话DTO
            ChatSessionDTO session = new ChatSessionDTO();
            session.setUserId(userId);
            session.setSessionTitle(sessionTitle);
            session.setStatus("active");
            session.setSessionType(sessionType);
            session.setMessageCount(0);
            session.setLastActiveTime(new Date());
            session.setCreateTime(new Date());
            session.setUpdateTime(new Date());
            
            // 保存会话到数据库
            int result = chatSessionMapper.createSession(session);
            if (result <= 0) {
                throw new RuntimeException("创建会话失败");
            }
            
            // 获取生成的sessionId
            Long sessionId = session.getSessionId();
            if (sessionId == null) {
                throw new RuntimeException("会话ID生成失败");
            }
            
            // 初始化Redis缓存
            initializeRedisChatMemory(sessionId);
            
            log.info("{}会话创建成功: sessionId={}, userId={}, title={}", 
                    sessionType, sessionId, userId, session.getSessionTitle());
            
            return session;
            
        } catch (Exception e) {
            log.error("创建{}会话失败: userId={}, error={}", sessionType, userId, e.getMessage(), e);
            throw new RuntimeException("创建" + sessionType + "会话失败", e);
        }
    }

    @Override
    public ChatSessionDTO getOrCreateCurrentSession(Long userId) {
        try {
            List<ChatSessionDTO> sessions = chatSessionMapper.getSessionsByUserId(userId);
            if (sessions.isEmpty()) {
                // 如果没有会话，创建一个新的
                return createChatSession(userId, "新会话");
            }
            
            // 返回最后一个活跃的会话
            return sessions.stream()
                    .filter(session -> "active".equals(session.getStatus()))
                    .findFirst()
                    .orElse(sessions.get(0));
                    
        } catch (Exception e) {
            log.error("获取或创建当前会话失败: userId={}, error={}", userId, e.getMessage(), e);
            throw new RuntimeException("获取或创建当前会话失败", e);
        }
    }
    
    @Override
    public List<ChatSessionDTO> getUserSessions(Long userId) {
        try {
            return chatSessionMapper.getSessionsByUserId(userId);
        } catch (Exception e) {
            log.error("获取用户会话列表失败: userId={}, error={}", userId, e.getMessage(), e);
            throw new RuntimeException("获取用户会话列表失败", e);
        }
    }
    
    @Override
    public List<ChatSessionDTO> getUserSessionsByType(Long userId, String sessionType) {
        try {
            return chatSessionMapper.getSessionsByUserIdAndType(userId, sessionType);
        } catch (Exception e) {
            log.error("获取用户{}会话列表失败: userId={}, error={}", sessionType, userId, e.getMessage(), e);
            throw new RuntimeException("获取用户" + sessionType + "会话列表失败", e);
        }
    }
    
    @Override
    public ChatMemory getChatMemory(Long sessionId) {
        try {
            String redisKey = RedisConstant.CHAT_MEMORY + sessionId;
            List<Map<String, Object>> messageList = (List<Map<String, Object>>) redisTemplate.opsForValue().get(redisKey);
            
            log.info("从Redis获取ChatMemory: sessionId={}, redisKey={}, messageList={}", 
                    sessionId, redisKey, messageList != null ? messageList.size() : "null");
            
            if (messageList == null || messageList.isEmpty()) {
                // 如果Redis中没有，从数据库重建
                log.info("Redis中没有消息，从数据库重建ChatMemory: sessionId={}", sessionId);
                messageList = rebuildChatMemoryFromDatabase(sessionId);
                // 缓存到Redis
                redisTemplate.opsForValue().set(redisKey, messageList, REDIS_EXPIRE_TIME, TimeUnit.SECONDS);
                log.info("从数据库重建完成，消息数量: {}", messageList.size());
            }
            
            // 创建ChatMemory对象并加载所有消息
            ChatMemory chatMemory = MessageWindowChatMemory.builder()
                    .maxMessages(20) // 最多保存20条消息
                    .build();
            
            log.info("开始构建ChatMemory，消息数量: {}", messageList.size());
            
            for (Map<String, Object> messageMap : messageList) {
                String role = (String) messageMap.get("role");
                String content = (String) messageMap.get("content");
                
                log.debug("处理消息: role={}, content={}", role, content != null ? content.substring(0, Math.min(content.length(), 50)) + "..." : "null");
                
                if ("user".equals(role)) {
                    chatMemory.add(UserMessage.from(content));
                } else if ("assistant".equals(role)) {
                    chatMemory.add(AiMessage.from(content));
                }
            }
            
            log.info("ChatMemory构建完成，消息数量: {}", chatMemory.messages().size());
            return chatMemory;
            
        } catch (Exception e) {
            log.error("获取ChatMemory失败: sessionId={}, error={}", sessionId, e.getMessage(), e);
            // 返回空的ChatMemory
            return MessageWindowChatMemory.builder()
                    .maxMessages(20)
                    .build();
        }
    }
    
    @Override
    public void addUserMessage(Long sessionId, String content) {
        try {
            // 获取会话信息
            ChatSessionDTO session = chatSessionMapper.getSessionById(sessionId);
            if (session == null) {
                throw new RuntimeException("会话不存在: sessionId=" + sessionId);
            }
            
            // 消息去重：检查是否与上一条消息重复
            List<ChatMessageDTO> existingMessages = chatSessionMapper.getMessagesBySessionId(sessionId);
            if (!existingMessages.isEmpty()) {
                ChatMessageDTO lastMessage = existingMessages.get(existingMessages.size() - 1);
                if ("user".equals(lastMessage.getRole()) && content.equals(lastMessage.getContent())) {
                    log.warn("检测到重复消息，跳过存储: sessionId={}, content={}", sessionId, content);
                    return;
                }
            }
            
            // 计算消息顺序
            int messageOrder = existingMessages.size() + 1;
            
            // 创建消息对象
            ChatMessageDTO message = new ChatMessageDTO();
            message.setSessionId(sessionId);
            message.setUserId(session.getUserId());
            message.setRole("user");
            message.setContent(content);
            message.setMessageType("text");
            message.setMessageOrder(messageOrder);
            message.setCreateTime(new Date());
            message.setUpdateTime(new Date());
            
            // 保存到数据库
            chatSessionMapper.addMessage(message);
            
            // 更新会话最后活跃时间
            chatSessionMapper.updateLastActiveTime(sessionId);
            
            // 更新Redis中的ChatMemory
            updateRedisChatMemory(sessionId);
            
            log.info("用户消息添加成功: sessionId={}, userId={}, messageOrder={}", sessionId, session.getUserId(), messageOrder);
            
        } catch (Exception e) {
            log.error("添加用户消息失败: sessionId={}, error={}", sessionId, e.getMessage(), e);
            throw new RuntimeException("添加用户消息失败", e);
        }
    }

    @Override
    public void addAiMessage(Long sessionId, String message) {
        try {
            // 获取会话信息以获取userId
            ChatSessionDTO session = chatSessionMapper.getSessionById(sessionId);
            if (session == null) {
                throw new RuntimeException("会话不存在: sessionId=" + sessionId);
            }
            
            // 获取当前会话的消息数量，用于设置messageOrder
            Integer currentMessageCount = chatSessionMapper.getMessageCountBySessionId(sessionId);
            int messageOrder = (currentMessageCount != null ? currentMessageCount : 0) + 1;
            
            // 创建消息DTO
            ChatMessageDTO messageDTO = new ChatMessageDTO();
            messageDTO.setSessionId(sessionId);
            messageDTO.setUserId(session.getUserId()); // 从会话中获取userId
            messageDTO.setRole("assistant");
            messageDTO.setContent(message);
            messageDTO.setMessageType("text");
            messageDTO.setMessageOrder(messageOrder);
            messageDTO.setCreateTime(new Date());
            messageDTO.setUpdateTime(new Date());
            
            // 保存到数据库
            int result = chatSessionMapper.addMessage(messageDTO);
            if (result <= 0) {
                throw new RuntimeException("保存AI消息失败");
            }
            
            // 更新会话的最后活跃时间
            chatSessionMapper.updateLastActiveTime(sessionId);
            
            // 更新Redis缓存中的ChatMemory
            updateRedisChatMemory(sessionId);
            
            log.info("AI消息添加成功: sessionId={}, userId={}, messageOrder={}", 
                    sessionId, session.getUserId(), messageOrder);
                    
        } catch (Exception e) {
            log.error("添加AI消息失败: sessionId={}, error={}", sessionId, e.getMessage(), e);
            throw new RuntimeException("添加AI消息失败", e);
        }
    }

    @Override
    public List<ChatMessageDTO> getSessionMessages(Long sessionId) {
        try {
            return chatSessionMapper.getMessagesBySessionId(sessionId);
        } catch (Exception e) {
            log.error("获取会话消息失败: sessionId={}, error={}", sessionId, e.getMessage(), e);
            throw new RuntimeException("获取会话消息失败", e);
        }
    }

    @Override
    public List<ChatMessage> getChatMemoryMessages(Long sessionId) {
        try {
            ChatMemory chatMemory = getChatMemory(sessionId);
            return chatMemory.messages();
        } catch (Exception e) {
            log.error("获取ChatMemory消息失败: sessionId={}, error={}", sessionId, e.getMessage(), e);
            throw new RuntimeException("获取ChatMemory消息失败", e);
        }
    }

    @Override
    public void updateSessionTitle(Long sessionId, String title) {
        try {
            ChatSessionDTO session = new ChatSessionDTO();
            session.setSessionId(sessionId);
            session.setSessionTitle(title);
            session.setStatus("active"); // 确保status不为null
            session.setUpdateTime(new Date());
            
            int result = chatSessionMapper.updateSession(session);
            if (result <= 0) {
                throw new RuntimeException("更新会话标题失败");
            }
            
            log.info("会话标题更新成功: sessionId={}, title={}", sessionId, title);
        } catch (Exception e) {
            log.error("更新会话标题失败: sessionId={}, title={}, error={}", sessionId, title, e.getMessage(), e);
            throw new RuntimeException("更新会话标题失败", e);
        }
    }

    @Override
    public void deleteSession(Long sessionId, Long userId) {
        try {
            // 首先删除会话相关的所有消息
            int messageResult = chatSessionMapper.deleteSessionMessages(sessionId);
            log.info("删除会话消息完成: sessionId={}, 删除消息数量={}", sessionId, messageResult);
            
            // 然后删除会话本身
            int sessionResult = chatSessionMapper.deleteSession(sessionId, userId);
            if (sessionResult <= 0) {
                throw new RuntimeException("删除会话失败，可能不存在或无权限");
            }
            
            // 删除Redis缓存
            String redisKey = RedisConstant.CHAT_MEMORY + sessionId;
            redisTemplate.delete(redisKey);
            
            log.info("会话删除成功: sessionId={}, userId={}, 删除消息数量={}", sessionId, userId, messageResult);
        } catch (Exception e) {
            log.error("删除会话失败: sessionId={}, userId={}, error={}", sessionId, userId, e.getMessage(), e);
            throw new RuntimeException("删除会话失败", e);
        }
    }

    @Override
    public void cleanupExpiredMemories() {
        try {
            // 这里可以实现清理过期记忆的逻辑
            // 比如删除超过一定时间的会话或消息
            log.info("清理过期记忆完成");
        } catch (Exception e) {
            log.error("清理过期记忆失败: error={}", e.getMessage(), e);
        }
    }

    /**
     * 从数据库重建ChatMemory对象
     */
    private List<Map<String, Object>> rebuildChatMemoryFromDatabase(Long sessionId) {
        try {
            List<ChatMessageDTO> messages = chatSessionMapper.getMessagesBySessionId(sessionId);
            log.info("从数据库获取消息: sessionId={}, 消息数量={}", sessionId, messages.size());
            
            List<Map<String, Object>> messageList = new ArrayList<>();
            
            for (ChatMessageDTO message : messages) {
                Map<String, Object> messageMap = new HashMap<>();
                messageMap.put("role", message.getRole());
                messageMap.put("content", message.getContent());
                messageMap.put("messageType", message.getMessageType());
                messageMap.put("messageOrder", message.getMessageOrder());
                messageMap.put("createTime", message.getCreateTime());
                messageList.add(messageMap);
                
                log.debug("数据库消息: role={}, content={}, order={}", 
                        message.getRole(), 
                        message.getContent() != null ? message.getContent().substring(0, Math.min(message.getContent().length(), 50)) + "..." : "null",
                        message.getMessageOrder());
            }
            
            log.info("数据库重建完成，消息数量: {}", messageList.size());
            return messageList;
        } catch (Exception e) {
            log.error("从数据库重建ChatMemory失败: sessionId={}, error={}", sessionId, e.getMessage(), e);
            // 返回空的ChatMemory
            return new ArrayList<>();
        }
    }

    /**
     * 获取下一条消息的顺序号
     */
    private Integer getNextMessageOrder(Long sessionId) {
        try {
            int count = chatSessionMapper.getMessageCountBySessionId(sessionId);
            return count + 1;
        } catch (Exception e) {
            log.error("获取消息顺序号失败: sessionId={}, error={}", sessionId, e.getMessage(), e);
            return 1;
        }
    }

    /**
     * 更新会话信息
     */
    private void updateSessionInfo(Long sessionId) {
        try {
            int messageCount = chatSessionMapper.getMessageCountBySessionId(sessionId);
            chatSessionMapper.updateLastActiveTime(sessionId);
            
            // 更新消息数量
            ChatSessionDTO session = chatSessionMapper.getSessionById(sessionId);
            if (session != null) {
                session.setMessageCount(messageCount);
                chatSessionMapper.updateSession(session);
            }
        } catch (Exception e) {
            log.error("更新会话信息失败: sessionId={}, error={}", sessionId, e.getMessage(), e);
        }
    }



    /**
     * 更新Redis缓存中的ChatMemory
     * @param sessionId 会话ID
     */
    private void updateRedisChatMemory(Long sessionId) {
        try {
            // 从数据库重建ChatMemory
            List<Map<String, Object>> messageList = rebuildChatMemoryFromDatabase(sessionId);
            
            // 存储到Redis
            String redisKey = RedisConstant.CHAT_MEMORY + sessionId;
            redisTemplate.opsForValue().set(redisKey, messageList, RedisConstant.CHAT_MEMORY_EXPIRE_TIME, TimeUnit.SECONDS);
            
            log.info("Redis ChatMemory更新成功: sessionId={}, messageCount={}", sessionId, messageList.size());
            
        } catch (Exception e) {
            log.error("更新Redis ChatMemory失败: sessionId={}, error={}", sessionId, e.getMessage(), e);
        }
    }

    /**
     * 初始化Redis缓存
     */
    private void initializeRedisChatMemory(Long sessionId) {
        try {
            String redisKey = RedisConstant.CHAT_MEMORY + sessionId;
            
            // 不直接存储ChatMemory对象，而是存储消息列表
            List<Map<String, Object>> messageList = new ArrayList<>();
            
            // 获取当前会话的所有消息
            List<ChatMessageDTO> messages = chatSessionMapper.getMessagesBySessionId(sessionId);
            
            for (ChatMessageDTO msg : messages) {
                Map<String, Object> messageMap = new HashMap<>();
                messageMap.put("role", msg.getRole());
                messageMap.put("content", msg.getContent());
                messageMap.put("messageType", msg.getMessageType());
                messageMap.put("messageOrder", msg.getMessageOrder());
                messageMap.put("createTime", msg.getCreateTime());
                messageList.add(messageMap);
            }
            
            // 存储可序列化的消息列表到Redis
            redisTemplate.opsForValue().set(redisKey, messageList, REDIS_EXPIRE_TIME, TimeUnit.SECONDS);
            
        } catch (Exception e) {
            log.error("初始化Redis缓存失败: sessionId={}, error={}", sessionId, e.getMessage(), e);
        }
    }

    /**
     * 生成会话标题
     */
    private String generateSessionTitle(String message) {
        if (!StringUtils.hasText(message)) {
            return "新对话";
        }
        
        // 简单的标题生成逻辑
        String title = message.trim();
        if (title.length() > 30) {
            title = title.substring(0, 30) + "...";
        }
        return title;
    }
}
